import socket
import threading
import logging
import time
from typing import Optional, Callable

# 配置日志
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('TCPClient')


class TCPClient:
    def __init__(self, server_ip: str, server_port: int,
                 reconnect_interval: int = 3,
                 data_handler=None):
        # TCP客户端类初始化
        # param server_ip: 服务器IP地址
        # param server_port: 服务器端口
        # param reconnect_interval: 重连间隔(秒)
        # param data_handler: 数据处理回调函数，格式: func(data: bytes, client: TCPClient)
        # 
        self.server_ip = server_ip
        self.server_port = server_port
        self.reconnect_interval = reconnect_interval
        self.data_handler = data_handler
        self.client_socket = None
        self.is_connected = False
        self.is_running = False
        self.receive_thread = None

    def connect(self) -> bool:
        # 连接到TCP服务器
        try:
            # 创建TCP套接字
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 设置超时
            self.client_socket.settimeout(5)
            # 连接服务器
            self.client_socket.connect((self.server_ip, self.server_port))
            self.client_socket.settimeout(None)  # 连接成功后取消超时
            self.is_connected = True
            logger.info(f"成功连接到服务器 {self.server_ip}:{self.server_port}")

            # 启动接收线程
            self.is_running = True
            self.receive_thread = threading.Thread(target=self._receive_data, daemon=True)
            self.receive_thread.start()
            return True
        except Exception as e:
            logger.error(f"连接服务器失败: {str(e)}")
            self.client_socket = None
            self.is_connected = False
            return False

    def _receive_data(self) -> None:
        # 接收服务器数据的内部方法
        while self.is_running and self.is_connected and self.client_socket:
            try:
                # 调用数据处理回调函数
                if self.data_handler:
                    self.data_handler(self)
            except Exception as e:
                if self.is_connected:
                    logger.error(f"接收数据失败: {str(e)}")
                    self.disconnect()

        # 如果需要自动重连
        if self.is_running and not self.is_connected:
            self._auto_reconnect()

    def _auto_reconnect(self) -> None:
        # 自动重连内部方法
        while self.is_running and not self.is_connected:
            logger.info(f"尝试重连服务器 {self.server_ip}:{self.server_port} (间隔 {self.reconnect_interval}秒)")
            time.sleep(self.reconnect_interval)
            if self.connect():
                break

    def send_data(self, data: bytes) -> bool:
        # 发送数据到服务器
        if not self.is_connected or not self.client_socket:
            logger.warning("未连接到服务器，无法发送数据")
            return False

        try:
            self.client_socket.sendall(data)
            logger.debug(f"发送数据到服务器: {len(data)} 字节")
            return True
        except Exception as e:
            logger.error(f"发送数据失败: {str(e)}")
            self.disconnect()
            return False

    def disconnect(self) -> None:
        # 断开与服务器的连接
        self.is_connected = False
        if self.client_socket:
            try:
                self.client_socket.close()
            except Exception as e:
                logger.error(f"关闭socket失败: {str(e)}")
            self.client_socket = None
        logger.info("已断开与服务器的连接")

    def start_auto_reconnect(self) -> None:
        # 启动自动重连机制
        if not self.is_running:
            self.is_running = True
            if not self.is_connected:
                reconnect_thread = threading.Thread(target=self._auto_reconnect, daemon=True)
                reconnect_thread.start()

    def stop(self) -> None:
        # 停止客户端
        self.is_running = False
        self.disconnect()
        if self.receive_thread and self.receive_thread.is_alive():
            self.receive_thread.join()
        logger.info("TCP客户端已停止")

    # 原方法名与属性名冲突，修改方法名
    def get_connection_status(self) -> bool:
        # 检查是否已连接到服务器
        return self.is_connected

    def __del__(self):
        # 析构函数，确保客户端正确停止
        self.stop()

